#include "threadpool.hpp"
#include <cstdio>
void fun1(int slp)
{
    printf("hello, fun1()! %d\n", std::this_thread::get_id());
    if (slp > 0)
    {
        printf(" ======= fun1() sleep %d  =========  %d\n", slp, std::this_thread::get_id());
        std::this_thread::sleep_for(std::chrono::milliseconds(slp));
    }
}
struct gfun
{
    int operator()(int n)
    {
        printf("%d hello gfun()! %d\n", n, std::this_thread::get_id());
        return 42;
    }
};

class A
{
public:
    static int Afun(int n = 0)
    {
        printf("%d hello, Afun()! %d\n", n, std::this_thread::get_id());
        return n;
    }
    static std::string Bfun(int n, std::string str, char c)
    {
        printf("%d hello, Bfun()! %s %d %d\n", n, str.c_str(), (int)c, std::this_thread::get_id());
        return str;
    }
};

int main()
{
    try
    {
        std::threadpool executor{50};
        A a;
        std::future<void> ff = executor.commit(fun1, 0);
        std::future<int> fg = executor.commit(gfun{}, 0);
        std::future<int> gg = executor.commit(a.Afun, 9999);
        std::future<std::string> gh = executor.commit(A::Bfun, 9998, "multi args", 123);
        std::future<std::string> fh = executor.commit([]() -> std::string { printf("hello, fh()! %d\n", std::this_thread::get_id()); return "hello, fh() ret!"; });
        printf(" =======  sleep ========= %d\n", std::this_thread::get_id());
        std::this_thread::sleep_for(std::chrono::microseconds(300));
        for (int i = 0; i < 50; i++)
            executor.commit(fun1, 100 * i);
        printf(" =======  commit all ========= %d idlsize = %d\n", std::this_thread::get_id(), executor.idlCount());
        printf(" =======  sleep ========= %d\n", std::this_thread::get_id());
        std::this_thread::sleep_for(std::chrono::microseconds(300));

        ff.get();
        printf("%d %s %d\n", fg.get(), fh.get().c_str(), std::this_thread::get_id());
        printf(" =======  sleep ========= %d\n", std::this_thread::get_id());
        std::this_thread::sleep_for(std::chrono::microseconds(300));
        printf(" =======  fun1,55 ========= %d\n", std::this_thread::get_id());
        executor.commit(fun1, 55).get();
        printf("end... %d\n", std::this_thread::get_id());

        std::threadpool pool(4);
        std::vector<std::future<int>> results;
        for (int i = 0; i < 8; i++)
        {
            results.emplace_back(
                pool.commit([i] {
                    printf("hello %d\n", i);
                    std::this_thread::sleep_for(std::chrono::microseconds(300));
                    printf("world %d\n", i);
                    return i * i;
                }));
        }
        printf(" =======  commit all2 ========= %d\n", std::this_thread::get_id());

        for (auto &&res : results)
            printf("%d ", res.get());
        printf("\n");
        return 0;
    }
    catch (std::exception &e)
    {
        printf("some unhappy thing happened %d\n", std::this_thread::get_id());
    }
}